package dk.mirasola.systemtraining.biddingsession.client.ui;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.Widget;
import dk.mirasola.systemtraining.biddingsession.client.i18n.SessionTexts;
import dk.mirasola.systemtraining.biddingsession.client.util.BiddingSessionAsyncCallback;
import dk.mirasola.systemtraining.biddingsession.shared.service.SessionService;
import dk.mirasola.systemtraining.biddingsession.shared.service.SessionServiceAsync;
import dk.mirasola.systemtraining.biddingsession.shared.transfer.BidBoardTO;
import dk.mirasola.systemtraining.biddingsession.shared.transfer.BidInitDataTO;
import dk.mirasola.systemtraining.biddingsession.shared.transfer.MakeBidResultTO;
import dk.mirasola.systemtraining.bridgewidgets.client.ui.BidHandler;
import dk.mirasola.systemtraining.bridgewidgets.client.ui.Bidbox;
import dk.mirasola.systemtraining.bridgewidgets.client.ui.BiddingSequenceTable;
import dk.mirasola.systemtraining.bridgewidgets.client.ui.HandPanel;
import dk.mirasola.systemtraining.bridgewidgets.client.ui.RenderUtil;
import dk.mirasola.systemtraining.bridgewidgets.shared.model.Bid;

import java.util.List;

public class BidSessionPanel extends Composite {
    interface BidSessionPanelUiBinder extends UiBinder<Widget, BidSessionPanel> {}
    private static BidSessionPanelUiBinder uiBinder = GWT.create(BidSessionPanelUiBinder.class);
    private static SessionServiceAsync sessionService = GWT.create(SessionService.class);    

    @UiField(provided = true)
    static SessionTexts texts = GWT.create(SessionTexts.class);

    private String biddingSetKey;
    private boolean serviceCallInProgress = false;

    @UiField
    HTML header;
    @UiField
    BoardsPanel boardsPanel;
    @UiField
    HandPanel handPanel;
    @UiField
    BiddingSequenceTable biddingSequenceTable;
    @UiField
    Bidbox bidbox;
    @UiField
    Button addCommentButton;
    @UiField
    TextArea commentArea;
    @UiField
    Button undoLastBidButton;
    @UiField
    FlowPanel commentsPanel;

    public BidSessionPanel(String biddingSetKey) {
        this.biddingSetKey = biddingSetKey;
        initWidget(uiBinder.createAndBindUi(this));

        initBoardsPanel();
        initUndoLastBidButton();
        initBidbox();
        initCommentPanel();
        initData();
    }

    private void initUndoLastBidButton() {
        undoLastBidButton.setVisible(false);
        undoLastBidButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                sessionService.undoBid(boardsPanel.getSelectedBoardKey(), new BiddingSessionAsyncCallback<BidBoardTO>() {
                    @Override
                    public void onSuccess(BidBoardTO result) {
                        boardsPanel.markSelectedToBidInSession();
                        updatePanel(result);
                    }
                });
            }
        });
    }

    private void initCommentPanel() {
        addCommentButton.setEnabled(false);
        commentArea.addKeyUpHandler(new KeyUpHandler() {
            @Override
            public void onKeyUp(KeyUpEvent event) {
                addCommentButton.setEnabled(commentArea.getText().length() > 0);
            }
        });
        addCommentButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                final String comment = commentArea.getText();
                // send comment to server
                sessionService.addComment(boardsPanel.getSelectedBoardKey(), comment, new BiddingSessionAsyncCallback<Void>() {
                    @Override
                    public void onSuccess(Void result) {
                        commentsPanel.add(new HTML(comment));
                        commentArea.setText("");
                        addCommentButton.setEnabled(false);
                    }
                });
            }
        });
    }


    private void initData() {
        sessionService.getBidInitData(biddingSetKey, new BiddingSessionAsyncCallback<BidInitDataTO>() {
            @Override
            public void onSuccess(BidInitDataTO data) {
                boardsPanel.setSessionBoards(data.getSessionBoards());
                boardsPanel.setSelectedBoardKey(data.getFirstBoard().getBoardKey());
                handPanel.setHeader(RenderUtil.renderSeatUppercaseFirst(data.getSeat()));
                header.setHTML(data.getBiddingSetName());
                updatePanel(data.getFirstBoard());
            }
        });
    }

    private void updateComments(List<String> comments) {
        commentsPanel.clear();
        if (comments != null) {
            for (String comment : comments) {
                commentsPanel.add(new HTML(comment));
            }
        }
        commentArea.setText("");
        addCommentButton.setEnabled(false);
    }

    private void initBidbox() {
        bidbox.setBidHandler(new BidHandler() {
            public void onBid(final Bid bid) {
                bidbox.setBiddingSequence(null);
                addCommentButton.setEnabled(false);
                undoLastBidButton.setEnabled(false);
                serviceCallInProgress = true;
                sessionService.makeBid(boardsPanel.getSelectedBoardKey(), bid, new BiddingSessionAsyncCallback<MakeBidResultTO>() {
                    @Override
                    public void onSuccess(MakeBidResultTO res) {
                        serviceCallInProgress = false;
                        if (res.isBiddingSequenceFinish()) {
                            boardsPanel.markSelectedFinish();
                        } else {
                            boardsPanel.markSelectedBidInSession();
                        }
                        if (res.getNextBoard() == null) {

                            HasWidgets container = (HasWidgets) getWidget();
                            container.clear();
                            HTML completed = new HTML(texts.sessionCompleted());
                            completed.addStyleName("sessionCompleted");
                            container.add(completed);
                        } else {
                            boardsPanel.setSelectedBoardKey(res.getNextBoard().getBoardKey());
                            updatePanel(res.getNextBoard());
                        }
                    }
                });
            }
        });
    }

    private void updatePanel(BidBoardTO bidBoard) {
        biddingSequenceTable.setBiddingSequence(bidBoard.getBiddingSequence());
        handPanel.setHand(bidBoard.getHand());
        if (bidBoard.isLastBidUndoable()) {
            bidbox.setBiddingSequence(null);
            undoLastBidButton.setEnabled(true);
        } else {
            bidbox.setBiddingSequence(bidBoard.getBiddingSequence());
            undoLastBidButton.setEnabled(false);
        }
        boardsPanel.setSelectedBoardKey(bidBoard.getBoardKey());
        updateComments(bidBoard.getComments());
        undoLastBidButton.setVisible(bidBoard.isLastBidUndoable());
    }

    private void initBoardsPanel() {
        boardsPanel.setChangeHandler(new ChangeHandler() {
            @Override
            public void onChange(ChangeEvent event) {
                if (!serviceCallInProgress) {
                    String boardId = boardsPanel.getSelectedBoardKey();
                    sessionService.getBidBoard(boardId, new BiddingSessionAsyncCallback<BidBoardTO>() {
                        @Override
                        public void onSuccess(BidBoardTO result) {
                            updatePanel(result);
                            undoLastBidButton.setFocus(true);
                        }
                    });
                }
            }
        });
    }
}
